/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.iprojectmanager.businessclass;

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.iprojectmanager.entities.*;

/**
 *
 * @author Enrique
 */
public class GanttControl extends HttpServlet{
    
    public static final int WEEK = 0;
    public static final int MONTH = 1;
    public static final int YEAR = 2;
    public static final long SDAY = 86400;
    public static final long SWEEK = 604800;
    public static final long SMONTH = 2620800;
    public static final long SYEAR = 31449600;
            
    
    @Override
    public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException{
        String opcionlider = request.getParameter("resultadosproyecto");
        if(opcionlider.compareToIgnoreCase("")!=0){
            if(opcionlider.compareToIgnoreCase("Mostrar Informacion")==0){
                RequestDispatcher disp = request.getRequestDispatcher("inicio");
                disp.forward(request, response);
            }else if(opcionlider.compareToIgnoreCase("Mostrar Gantt")==0){
                RequestDispatcher disp = request.getRequestDispatcher("VistaGantt");
                disp.forward(request, response);
            }else if(opcionlider.compareToIgnoreCase("Generar Reporte")==0){
                RequestDispatcher disp = request.getRequestDispatcher("inicio");
                disp.forward(request, response);
            }else{
                RequestDispatcher disp = request.getRequestDispatcher("inicio");
                disp.forward(request, response);
            }
        }
    }
    
    public String buildTable(Proyecto proyecto){
        int calunit = this.calculeUnit(proyecto);
        long dur = this.durProyecto(proyecto);
        return this.buildHeader(calunit,this.getTableBody(proyecto),this.longProyecto(dur, calunit));
    }
    
    public String buildHeader(int unit,String body,int dur){
        String rest = 
                "<h3 style=\"text-align:center;\">"+
                "<span>Gantt</span>"+
                "</h3>"+
                "<p class=\"p1\">"+
                "<span>"+
                "<table border=\"1\" align=\"center\">"+
                "<tbody>" +
                "<tr>" +
                "<th rowspan=\"2\" align=\"center\" valign=\"middle\">Actividades</th>" +
                "<th colspan=\""+
                String.valueOf(dur) +
                "\" align=\"center\" valign=\"middle\">" +
                this.getUnit(unit) +
                "</th>" +
                "</tr>" +
                "</span>" +
                "</p>";
        rest += body;
        rest += "</tbody>" +
                "</table>";
        return rest;
    }
    
    public String getUnit(int unit){
        String unitout = "";
        if(unit == WEEK){
            unitout = "Semanas";
        }else if(unit == MONTH){
            unitout = "Meses";
        }else if(unit == YEAR){
            unitout = "Años";
        }
        return unitout;
    }
    
    public int calculeUnit(Proyecto proyecto){
        int unit = 0;
        long weeks,months,diff = this.durProyecto(proyecto);
        weeks = diff/SWEEK;
        if(weeks>24){
            unit = 1;
            months = diff/SMONTH;
            if(months>24){
                unit = 2;
            }
        }
        return unit;
    }
    
    public long durProyecto(Proyecto proyecto){
        Date inicio = proyecto.getFechainicio();
        Date fin = proyecto.getFechafin();
        return (fin.getTime() - inicio.getTime())/1000;
    }
    
    public String getTextUnit(String color){
        return "<td style=\"background-color:" +
                color +
                ";color:" +
                color +
                "\">|||||</td>";
    }
    
    public String getTextActivity(Actividad act,int total, int unit, int prev){
        String text = "";
        text += "<tr>" +
                "<td>" +
                act.getNombre() +
                "</td>";
        for(int i=0;i<total;i++){
            if(i>=prev&&i<(prev+this.durActivity(act, unit))){
                text += this.getTextUnit("#00ff00");
            }else{
                text += this.getTextUnit("#0000ff");
            }
        }
        text += "</tr>";
        return text;
    }
    
    public String getTableBody(Proyecto proyecto){
        String body = "";
        int unit = this.calculeUnit(proyecto), durpro = this.longProyecto(this.durProyecto(proyecto),unit);
        body = this.getAux2(durpro);
        orderActivity order = new orderActivity();
        orderActivity ordena = new orderActivity();
        ordena.consList();
        order.consList();
        for(Actividad lista : proyecto.getActividades()){
            System.out.println(lista.getNombre());
            order.addList(new orderActivity(lista,proyecto));
        }
        //Collections.sort(order.getList());
        //order.ordenaLista();
        order.imprimeOrder();
        for(int i=0;i<order.getList().size();i++){
            order.ordenaLista();
            order.imprimeOrder();
            if(i==0){
                body += this.getTextActivity(order.getListActividad(i),durpro,unit,0);
            }else{
                body += this.getTextActivity(order.getListActividad(i),durpro,unit,this.getPrevious(i, order,unit));
            }
        }
        return body;
    }
    
    public int durActivity(Actividad act, int unit){
        int dur;
        long init = act.getFechaInicio().getTime(), fin = act.getFechaEntrega().getTime(),ldur;
        ldur = (fin - init)/1000;
        if(unit == WEEK){
            dur = (int)(ldur/SWEEK);
            if(((((float)ldur/(float)SWEEK))-dur)>=0.5){
                dur += 1;
            }
        }else if(unit == MONTH){
            dur = (int)(ldur/SMONTH);
            if(((((float)ldur/(float)SMONTH))-dur)>=0.5){
                dur += 1;
            }
        }else{
            dur = (int)(ldur/SYEAR);
            if(((((float)ldur/(float)SYEAR))-dur)>=0.5){
                dur += 1;
            }
        }
        return dur;
    }
    
    public int longProyecto(long durproyecto,int unit){
        int value=0;
        if(unit == WEEK){
            value = (int)(durproyecto/SWEEK);
        }else if(unit == MONTH){
            value = (int)(durproyecto/SMONTH);
        }else{
            value = (int)(durproyecto/SYEAR);
        }
        return value;
    }
    
    public String getAux(int i){
        return "<td style=\"text-align:center;\">" +
                String.valueOf(i) +
                "</td>";
    }
    
    public String getAux2(int dur){
        String subheader="";
        subheader += "<tr>";
        for(int i=0;i<dur;i++){
            subheader += this.getAux(i+1);
        }
        subheader += "</tr>";
        return subheader;
    }
    
    //getPrevious calcula el tiempo previo a una actividad dentro de una lista identificada por id.
    public int getPrevious(int id,orderActivity order, int unit){
        orderActivity aux = order.getList().get(id),auz;
        Actividad aux1 = aux.getActividad(),aux2;
        int prev = 0;
        for(int i=0;i<id;i++){
            auz = order.getList().get(i);
            aux2 = auz.getActividad();
            if(aux.getDiff()==auz.getDiff()){
                getPrevious(i,order,unit);
                i = id;
            }else{
                prev += this.durActivity(aux2, unit);
            }
        }
        return prev;
    }
}

class orderActivity implements Comparable{
    
    private Actividad act;//Actividad a ordenar
    private long diff;//Diferencia entre el inicio del proyecto y el inicio de la actividad
    private long dur;//Duración de la actividad
    
    private List<orderActivity> order;
    
    orderActivity(Actividad act, long diff, long dur){
        this.act = act;
        this.diff = diff;
        this.dur = dur;
    }
    
    orderActivity(Actividad act, Proyecto proyecto){
        this.act = act;
        this.diff = this.act.getFechaInicio().getTime();
        this.diff -= proyecto.getFechainicio().getTime();
        this.diff = this.diff/1000;
        this.dur = this.act.getFechaEntrega().getTime();
        this.dur -= this.act.getFechaInicio().getTime();
        this.dur = this.dur/1000;
        impOrder(this);
    }
    
    orderActivity(){
    }
    
    public void imprimeOrder(){
        for(int i=0;i<this.order.size();i++){
            this.impOrder(this.getListOrder(i));
        }
    }
    
    private void impOrder(orderActivity order){
        System.out.println("Actividad: "+order.act.getNombre());
        System.out.println("Diff: "+order.diff);
        System.out.println("Dur: "+order.dur);
    }
    
    public void consList(){
        order = new ArrayList<orderActivity>();
    }
    
    public void addList(orderActivity n){
        order.add(n);
    }
    
    public Actividad getListActividad(int i){
        return order.get(i).getActividad();
    }
    
    public orderActivity getListOrder(int i){
        return order.get(i);
    }
    
    public void ordenaLista(){
        /*List<orderActivity> aux = new ArrayList<orderActivity>();
        List<orderActivity> ordenada = new ArrayList<orderActivity>();
        long min = 86400;
        int posmin = order.size(), posmax = order.size()+1;
        for(int i=0;i<order.size();i++){
            if(order.get(i).getDur() < min){
                ordenada.add(posmin, order.get(i));
                min = order.get(i).getDur();
                posmin -= 1;
            }else{
                ordenada.add(posmax, order.get(i));
                posmax += 1;
            }
        }*/
        Collections.sort(order);
    }
    
    public long getDiff(){
        return this.diff;
    }
    
    public long getDur(){
        return this.dur;
    }
    
    public Actividad getActividad(){
        return this.act;
    }
    
    public List<orderActivity> getList(){
        return order;
    }

    public int compareTo(Object o) {
        orderActivity actividad2 = (orderActivity)o;
        return ((Long)this.getDiff()).compareTo((Long)actividad2.getDur());
    }
}